"""
K线数据获取模块
"""
import time
from typing import List, Dict
from datetime import datetime, timedelta
from src.okx.client import OKXClient
from src.okx.models import KlineData
from src.utils.logger import get_logger

logger = get_logger(__name__)


class KlineDataFetcher:
    """K线数据获取器"""

    def __init__(self, client: OKXClient):
        self.client = client
        self.request_count = 0
        self.last_request_time = 0

    def _rate_limit(self, requests_per_second: int = 10):
        """
        速率限制 (OKX API限制每秒10个请求)

        Args:
            requests_per_second: 每秒请求数限制
        """
        min_interval = 1.0 / requests_per_second
        elapsed = time.time() - self.last_request_time

        if elapsed < min_interval:
            time.sleep(min_interval - elapsed)

        self.last_request_time = time.time()
        self.request_count += 1

    def fetch_klines(self, symbol: str, timeframe: int, limit: int = 100) -> List[KlineData]:
        """
        获取K线数据

        Args:
            symbol: 交易对
            timeframe: 时间框架 (分钟)
            limit: 获取的K线数量

        Returns:
            K线数据列表
        """
        self._rate_limit()

        try:
            klines = self.client.get_klines(symbol, timeframe, limit)
            logger.info(f"获取K线成功: {symbol} {timeframe}分钟, 共{len(klines)}条")
            return klines
        except Exception as e:
            logger.error(f"获取K线异常: {symbol} {timeframe}分钟, 错误: {str(e)}")
            return []

    def fetch_multiple_timeframes(self, symbol: str, timeframes: List[int],
                                  limit: int = 100) -> Dict[int, List[KlineData]]:
        """
        获取多个时间框架的K线数据

        Args:
            symbol: 交易对
            timeframes: 时间框架列表
            limit: 每个周期获取的K线数量

        Returns:
            {时间框架: K线数据列表} 字典
        """
        result = {}

        for tf in timeframes:
            klines = self.fetch_klines(symbol, tf, limit)
            result[tf] = klines

        return result

    def fetch_historical_klines(self, symbol: str, timeframe: int,
                               start_date: datetime, end_date: datetime) -> List[KlineData]:
        """
        获取历史K线数据 (用于回测)

        使用 /market/history-candles 端点支持分页获取

        Args:
            symbol: 交易对
            timeframe: 时间框架 (分钟)
            start_date: 开始日期
            end_date: 结束日期

        Returns:
            K线数据列表
        """
        self._rate_limit()

        try:
            # 使用新的 get_historical_klines 方法，支持分页
            klines = self.client.get_historical_klines(symbol, timeframe, start_date, end_date)
            if klines:
                logger.info(f"获取历史K线成功: {symbol} {timeframe}分钟 ({start_date} - {end_date}), 共{len(klines)}条")
            else:
                logger.warning(f"获取历史K线为空: {symbol} {timeframe}分钟 ({start_date} - {end_date})")
            return klines
        except Exception as e:
            logger.error(f"获取历史K线异常: {symbol} {timeframe}分钟, 错误: {str(e)}")
            return []

    def validate_klines(self, klines: List[KlineData]) -> bool:
        """
        验证K线数据的有效性

        Args:
            klines: K线数据列表

        Returns:
            是否有效
        """
        if not klines:
            logger.warning("K线数据为空")
            return False

        # 检查K线数量
        if len(klines) < 20:
            logger.warning(f"K线数据不足: {len(klines)} < 20")
            return False

        # 检查OHLC数据完整性
        for kline in klines:
            if kline.open <= 0 or kline.close <= 0:
                logger.error(f"K线数据异常: timestamp={kline.timestamp}")
                return False

            # 检查high >= low
            if kline.high < kline.low:
                logger.error(f"K线数据异常: high < low, timestamp={kline.timestamp}")
                return False

        # 检查时间戳是否递增
        for i in range(1, len(klines)):
            if klines[i].timestamp <= klines[i-1].timestamp:
                logger.error(f"K线时间戳异常: {klines[i].timestamp} <= {klines[i-1].timestamp}")
                return False

        return True
